
The PlaySample module version 2.45        26 Sep 1995
==================================

by Rick Hudson,
rick@actrix.gen.nz


The PlaySample module is a module that can play samples in a variety of
formats straight from the disc file. It is designed to play samples
accurately at their recorded rate independantly of current sound system
speed and (hopefully) the effects of VIDC enhancers.

There are two way that the module can play the sample at the required speed:

Frequency modulation:

  The default method is to leave the system sound frequency as it is and use
  frequency modulation to ensure that new data is sent to the sound system at
  the required frequency. If the required frequency is higher than the system
  frequency then samples will be skipped as neccessary to keep pace with the
  system frequency. If the required frequency is lower then samples will be
  sent twice occasionally while the system frequency 'catches up'. The
  modulation also allows the frequency to be 'tuned' (using PlaySample_Speed)
  to correct for unusual VIDC frequencies, for example. As no interpolation
  takes place there may be a slight quality drop.
  
Unmodulated:

  The alternative is to set the system sound frequency to a frequency as
  close as possible to the required frequency and just send the samples
  verbatum. This means that the sample will be reproduced cleanly but there
  is no fine control of the frequency and so may sound fast or slow.

The PlaySample module provides a small number of commands and some SWIs that
can be used to control the playback of samples. It's usual use will be from
the desktop through a program like SoundCon or MTaudio. Command line use is
quite limited as it can only play Armadeus files.

Terminology notes for this text:

  - A "sample" is the wave amplitude at a given time for ONE given channel

  - A "sample frame" or just "frame" is the set of samples on ALL channels
    at a given time. For a mono sound this will mean the same as a sample,
    but for a stereo sound there are two samples per sample frame (one for
    each channel)

  - A "sample file" is the disc file containing samples

  - "Sample period" is the time interval between sending sample frames to
    the sound system

  - "Sample frequency" or "playback frequency" is the rate of sending
    sample frames to the sound system. The actual number of bytes per
    second will depend on the bits per sample and the number of channels.


Commands:
========

  - SPlay <filename> [<start>]

      Start playing the sound in file <filename>. Optionally, the sound
      can be started at byte offset <start>. Note that if manual polling is
      enabled then *SMore must be used regularly to maintain playback. The
      sound must be an Armadeus format file otherwise unpredicable things
      will happen. Playing of other formats is only supported through the
      SWI interface.

  - SStop

      Stop the sound playing and release the sound system.

  - SPause

      Toggle start/stop of sound playback.

  - SMore

      In manual polling mode, this command must be executed regularly (say
      twice a second at least) to maintain playback continuity. If the
      buffer 'runs out' then the sound is stopped (equivalent to an
      explicit *SPause) until the buffer is refilled. This command has no
      effect in automatic polling mode or when no sound is playing.

  - SAuto

      Switch on automatic polling (see below).

  - SManual

      Switch off automatic polling (see below).

  - SVolume <vol>

      Set the volume of PlaySample. <vol> is in the range 1 (quiet) thru 127
      (100%) to 255 (200% amplification). The 1-127 is the same as the system
      command *Volume, the 128-255 amplification feature is new since version
      2.43 of PlaySample. For amplified volume, clipping may occur when
      individual samples are amplified too much. Note that PlaySample uses a
      volume setting independant of the system volume so that the system
      command *Volume will have no effect on it.

  - SSpeed <num>

      <num> is a tuning value for PlaySample to allow for the correction of
      playback speed when the actual VIDC frequency is different from what
      the sound system is expecting. <num> is <expected freq>/<actual freq>
      * &10000, eg 24000/25175*&10000 = 62447 will slow the sound down
      sightly if it is too fast. The actual frequency can be obtained from
      VduVariable &AC in RISC OS (except if it's very old) and the expected
      frequency is the nearest multiple of 4000Hz to it. Desktop front ends
      should select this automatically.

SWIs:
====

  IMPORTANT NOTE:
  
  The SWI interface was changed after version 2.43 and is not backward
  compatible! Software designed to work with version 2.43 or earlier will
  probably not work with newer versions.
  
  PlaySample_Open is now called slightly differently and the SWI
  PlaySample_BeginEnd has been added. PlaySample_Config has also had an
  interface change to make it more versatile and future proof.

  Summary:

  PlaySample_Status   (&CF8C0)
  PlaySample_Open     (&CF8C1)
  PlaySample_SetPtr   (&CF8C2)
  PlaySample_Play     (&CF8C3)
  PlaySample_Stop     (&CF8C4)
  PlaySample_Pause    (&CF8C5)
  PlaySample_Config   (&CF8C6)
  PlaySample_Volume   (&CF8C7)
  PlaySample_Speed    (&CF8C8)
  PlaySample_Version  (&CF8C9)
  PlaySample_BeginEnd (&CF8CA)
  
  Details:

  PlaySample_Status (&CF8C0)
    Playback monitors can use this call to determine what the state of the
    player is. R2, R4 and R5 can be used to determine the time offset into
    the sample using t=R2 / (16e6/R4) / (bits per sample/8*channels).
    On entry: -
    On Exit:  R0 : bit  0 = set if sound is playing
                   bit  1 = set if sound paused
                   bit  2 = set if sound finished
                   bit  3 = set if a sound file is open
                   bit  4 = set if module has voice claimed
                   bit 16 = set if manual polling enabled
                   bit 17 = set if frequency modulation disabled
              R1 = pointer to file leafname
              R2 = current byte offset into sample file
              R3 = size of sample file in bytes
              R4 = sample period (microseconds * 16)
              R5 = voice mode: bit 0 = set if stereo, clear if mono
                               bits 1-7: 0 = 8-bit
                                         1 = 16-bit
                                         2 = 4-bit MS ADPCM
                                         3 = 4-bit DVI ADPCM

  PlaySample_Open (&CF8C1)
    Open a file and define its format. Playback is not started (pause mode
    is entered). Use PlaySample_BeginEnd to set play range then
    PlaySample_Play to start the playback.
    On entry: R0 = pointer to filename to open (0 for current file)
              R1 = sample format:
                   <=0 - 8 bit linear signed
                     1 - 8 bit linear unsigned
                     2 - 8 bit mu-law
                     3 - 8 bit A-law
                     4 - 8 bit VIDC
                   5-7 - undefined/reserved
                     8 - 16 bit linear signed little endian
                     9 - 16 bit linear signed big endian
                    10 - 16 bit linear unsigned little endian
                    11 - 16 bit linear unsigned big endian
                 12-15 - undefined/reserved
                    16 - Microsoft (MS) ADPCM
                    17 - DVI ADPCM
                  >=18 - undefined               
              R2 = sample period in microseconds * 16 (if R2=0 and R1=-1,
                   period obtained from first byte of file). eg for 22050Hz,
                   R2=16e6/22050 = 727. Default frequency (if R2 is invalid)
                   is 11111Hz.
              R3 = number of channels (<>2 for mono, 2 for stereo).
              R4 = unused
              if R3<>2 (mono) then
                 R5 = echo delay in sample periods for simulated stereo
                      effect (max 2048). R5=(echo time)*(playfrequency), eg
                      R5 = 0.1secs * 11111Hz = 1111. Normal mono if R5=0.
              if R3=2 (stereo) then
                 R5 = stereo interleave (bytes left, bytes right, etc). eg 1
                      for PCM WAVEs, 8 for AudioWorks. This number must be a
                      power of 2 (ie 1, 2, 4, 8, etc) and the buffer size
                      must be a multiple of 2*interleave to ensure that a
                      left/right chunk is always completely in the buffer.
              if R1=8 or 9 (ADPCM formats) then
                 R6 = number of compressed sample frames in block. ie
                      nFramesPerBlock (bytes &12 and &13 of the WAVE 'fmt '
                      chunk) - frames in block header. ie nFramesPerBlk-1
                      for DVI ADPCM and nFramesPerBlock-2 for MS ADPCM.
    On exit:  R0 - R7 undefined

    This call will require knowledge of the file format to fill in all the
    registers properly. ADPCM WAVEs in particular need precise information
    from the header block. Contact the author if you want more information
    on any of the formats supported by SoundCon or if you can supply some
    information on any formats it doesn't support!

    Note that to play a normal armadeus sample at the default frequency,
    R1=-1, R2=R3=R4=0.

  PlaySample_SetPtr (&CF8C2)
    On entry: R0 = absolute file offset to move to. Used for cueing etc.
    On exit:  all registers preserved

  PlaySample_Play (&CF8C3)
    Start playing the sound from the current pointer position.
    On entry: No parameters
    On exit:  R0 undefined, other registers preserved

  PlaySample_Stop (&CF8C4)
    If a sound is playing, it is stopped and the sound system is freed. No
    more playback will be possible until another PlaySample_Open is done.
    On entry: No parameters
    On exit:  R0 undefined, other registers preserved

  PlaySample_Pause (&CF8C5)
    Stop the sound playing but playback can be restarted with
    PlaySample_Play. PlaySample_SetPtr can be called while paused.
    On entry: No parameters
    On exit:  All registers preserved

  PlaySample_Config (&CF8C6)
    Set/read playback buffer size and/or behaviour flags. The flags are set
    using newflags = (oldflags AND (NOT R1) EOR R2). The flags are:
      bit 0: 0=auto poll, 1=manual poll
      bit 1: 0=frequency modulation, 1=no frequency modulation
    On entry: R0 = buffer size (0 for no change - default is 8k)
              R1 = flags clear mask
              R2 = flags exclusive-or mask
    On exit:  R0 = buffer size (after any change)
              R1 = flags (after any change)
              R2 = undefined
              other registers preserved

    Important note: For playing ADPCM samples, the buffer size MUST be a
    multiple of the sample block size. ie size = n*nBlockAlign. For other
    samples, the buffer must be a multiple of the number of bytes per frame.
    eg for 16 bit stereo, the buffer must be a multiple of 4 bytes.

  PlaySample_Volume (&CF8C7)
    Set or read the PlaySample volume. Note that PlaySample's volume is
    independant of the system volume. 
    On entry: R0 = volume (0 for no change, 1=quiet, 127=loud=100%, 255=200%)
    On exit:  R0 = volume setting
              other registers preserved

  PlaySample_Speed (&CF8C8)
    Tune Playsample for sound system speed inaccuracies. See the description
    of *SSpeed (above) for details.
    On entry: R0 = tuning value (<expected freq> / <actual freq> * &10000)
    On exit:  R0 undefined
              other registers preserved

  PlaySample_Version (&CF8C9)
    Return the version number*100 of PlaySample (241 for version 2.41)
    On entry: -
    On exit:  R0 = version number * 100
              other registers preserved
    
  PlaySample_BeginEnd (&CF8CA)
    Define the start and end points for sample playback as byte offsets from
    the start of the file. If the current file pointer is outside the given
    play range, it is set to the beginning point.
    so that PlaySample_Play will start from the file offset in R0.
    On entry: R0 = byte offset to start from
              R1 = byte offset to end at+1 (ie R1 = R0 + #bytes to play). If               R1<=R0 it will play to the end of the file.
    On exit:  all regisiters preserved

Note that it is not necessary to stop a sample playing before starting a new
one or killing the module.


Polling mechanism
-----------------

The normal polling mechanism makes use of OS_AddCallBack to allow delayed
access to disc SWIs from inside the voice generator code. This may cause
problems in RISC OS 2 (although this version seems ok) where there was a bug
in the call back handler. If errors start occurring (like address exceptions)
then first ensure that the IRQUtils module has been loaded which should fix
this problem. If the PlaySample module is still causing problems then manual
polling can be used (software may or may not allow you to change this).

If the sample stops unexpectedly when playing off a floppy disc, try either
decreasing the buffer size to keep the drive running continuously or
increase it to ensure that enough data is in the memory to cover the time it
takes to restart the floppy from a stop. This is a trial and error thing!

Heavy interrupt activity of any sort may also cause PlaySample to stop
playing momentarily because the callback system will be delayed a long long
in these circumstances. Sending data to the printer a common cause of
this. Again, increasing the buffer size may alleviate this.
